(library (lib parallelism)
  (export run-in-parallel)

  (import
   (except (rnrs base) let-values map)
   (only (guile)
         lambda* λ)
   (ice-9 futures)
   (srfi srfi-1))

  (define run-in-parallel
    (λ (segments map-proc reduce-proc reduce-init)
      "Use futures to run a procedure in parallel, if
multiple cores are available. Take a list of SEGMENTS as
input, which are ranges of values to work on. MAP-PROC is
applied to the SEGMENTS using map. When the MAP-PROC calls
for all segments finished and returned values, the
REDUCE-PROC is applied to the map result using reduce and
the REDUCE-INIT argument."
      (let ([futures
             (map (λ (seg)
                    (make-future
                     ;; Need to wrap in a thunk, to not
                     ;; immediately start evaluating.
                     (λ () (map-proc seg))))
                  segments)])
        (let ([segment-results (map touch futures)])
          (reduce reduce-proc
                  reduce-init
                  segment-results))))))
